package com.huazai.yangge.cas;

import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.StampedLock;

/**
 * StampedLock 传统的读写线程具备 ReentrantLock的功能
 *
 * @author huazai
 * @date 2024/2/27
 */
public class StampedLockDemo {
    static int number = 37;
    static StampedLock stampedLock = new StampedLock();

    public void write() {
        final long stamp = stampedLock.writeLock();
        System.out.println(Thread.currentThread().getName() + "写线程准备修改");
        try {
            number += 13;
        } finally {
            stampedLock.unlockWrite(stamp);
        }
        System.out.println(Thread.currentThread().getName() + "写线程结束修改");
    }

    public void read() {
        final long stamp = stampedLock.readLock();
        System.out.println(Thread.currentThread().getName() + "come in readlock 4seconds continue。。。");

        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "线程正在读取中");

        }

        try {
            int result = number;
            System.out.println(Thread.currentThread().getName() + "获取成员变量result：" + result);
            System.out.println("写线程修改成功，读锁时候写锁无法接入，传统的读写互斥");
        } finally {
            stampedLock.unlockRead(stamp);
        }

    }

    //乐观读 读的时候也允许写锁介入
    public void tryOptimisticRead() {
        long stamp = stampedLock.tryOptimisticRead();
        int result = number;
        System.out.println("4秒前stampedLock.validate方法值（true无修改，false有修改） = " + stampedLock.validate(stamp));
        for (int i = 0; i < 4; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "正在读取" + i + "秒" + "stampedLock.validate方法值（true无修改，false有修改） = " + stampedLock.validate(stamp));
        }

        if (!stampedLock.validate(stamp)) {
            System.out.println("有人修改过----有写入操作 ");
            stamp = stampedLock.readLock();
            try {
                System.out.println("从乐观读升级为 悲观读");
                result = number;
                System.out.println("重新悲观读后 result = " + result);
            } finally {
                stampedLock.unlockRead(stamp);
            }
        }

        System.out.println(Thread.currentThread().getName() + "finally value = " + result);
    }

    public static void main(String[] args) {
        StampedLockDemo stampedLockDemo = new StampedLockDemo();
        //new Thread(() -> stampedLockDemo.read(), "readThread").start();
        //try {
        //    TimeUnit.SECONDS.sleep(1);
        //} catch (Exception e) {
        //    e.printStackTrace();
        //}
        //new Thread(() -> {
        //    System.out.println(Thread.currentThread().getName() + "-----come in");
        //    stampedLockDemo.write();
        //}, "writeThread").start();

        new Thread(() -> {
            stampedLockDemo.tryOptimisticRead();
        }, "readThread").start();

        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (Exception e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "-----come in");
            stampedLockDemo.write();
        }, "writeThread").start();
    }
}

